package server;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import server.exception.StockException;

/**
 * Diese Klasse stellt ein abstraktes Lager dar.
 * Was passieren soll, wenn ein Produkt entfernt wird, muss jede konkrete Instanz selber wissen.
 * @author reto
 *
 */
public abstract class AbstractStock {
	private Map<String,ProductLot> productLots;

	/**
	 * Erstellt eine Map von ProductLots und des dazugehörigen Produktenamens.
	 */
	public AbstractStock()
	{
		this.productLots = new HashMap<String,ProductLot>();	
	}
	/**
	 * Convenience Constructor
	 * @param productLots schon bekannte Produkte
	 */
	protected AbstractStock(final ProductLot... productLots) {
		this();
		for (final ProductLot lot : productLots) {
			this.productLots.put(lot.getProduct().getName(),lot);
		}
	}
	/**
	 * Falls sich das Produkt bisher nicht im Stock aufhielt, wird die Produktepalette um ein Produktgebinde erweitert. Ansonsten wird dem bestehenden Gebinde eines hinzugefügt.
	 * @param product Das Produkt, welches in den Wagen kommen soll
	 */
	public synchronized void addProduct(final Product product)
	{
		if(!this.productLots.containsKey(product.getName())) {
			this.productLots.put(product.getName(),new ProductLot(product, 0));
		}
		this.productLots.get(product.getName()).add();
			
	}
	/**
	 * Convenience Methode @see AbstractSock.removeProduct(String productName)
	 */
	public void removeProduct(final Product product) throws StockException {
		this.removeProduct(product.getName());
	}
	
	/**
	 * Ermittelt das monetäre Total für des Lagers 
	 * @return
	 */
	public synchronized double getTotal() {
		double total = 0;
		for (final ProductLot lot : this.productLots.values()) {
			total += lot.getProduct().getPrice() * lot.getAmount();
		}
		return total;
	}

	/**
	 * @return Eine Sicht (checkedCollection) der vorhanden Produkte-Gebinde
	 */
	public Collection<ProductLot> getProductLotsAsCollection() {
		return Collections.checkedCollection(this.productLots.values(),
				ProductLot.class);
	}
	
	public void removeAllProducts()
	{
		this.productLots.clear();
	}
	
	protected synchronized Map<String, ProductLot> getProductLots() {
		return this.productLots;
	}
	
	public abstract Product removeProduct(String productName) throws StockException;


}
